using System;
using System.Text;
using System.IO;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;
using System.Drawing;
using System.Diagnostics;
using ZedGraph;

public class ParItStreamCLI
{
    Pool myThreadPool;
    ThreadStart pd2ThreadStart;
    Thread pd2Thread;

    private class Options
    {
        private bool pHelp, pCreate, pExtract, pList, pTest, pProgressDialog, pDngs, pGzip;
        private int pThreads = 5;
        private string[] args;
        public string archive { get; set; }
        public List<string> files { get; set; }

        public Options(string[] args)
        {
            this.args = args;
            pHelp = pCreate = pExtract = pList = pTest = pProgressDialog = pDngs = pGzip = false;
            files = new List<string>();
        }

        public void parse()
        {
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i].Equals("-l"))
                    pList = true;
                else if (args[i].Equals("-d"))
                    pDngs = true;
                else if (args[i].Equals("-g"))
                    pGzip = true;
                else if (args[i].Equals("-c"))
                    pCreate = true;
                else if (args[i].Equals("-x"))
                    pExtract = true;
                else if (args[i].Equals("-t"))
                    pTest = true;
                else if (args[i].StartsWith("-j"))
                    pThreads = Convert.ToInt16(args[i].Substring(2));
                else if (args[i].Equals("-p"))
                    pProgressDialog = true;
                else
                    files.Add(args[i]);
            }
        }

        public override string ToString()
        {
            StringBuilder deString = new StringBuilder();

            foreach (string arg in args)
                deString.Append(arg + "\n");

            if (pHelp)
                deString.Append("Help: enabled\n");
            else
                deString.Append("Help: disabled\n");

            deString.Append(String.Format("Threads: {0}\n", pThreads));
            return deString.ToString();
        }

        public bool help() { return pHelp; }
        public int getThreads() { return pThreads; }
        public bool getExtract() { return pExtract; }
        public bool getCreate() { return pCreate; }
        public bool getTest() { return pTest; }
        public bool getProgressionDialogSwitch() { return pProgressDialog; }
        public bool getList() { return pList; }
        public bool getGzip() { return pGzip; }
        public bool getDngs() { return pDngs; }
    }

    private class ProgressDialog2 : Form
    {
        private class SpinnerThreads : NumericUpDown
        {
            public SpinnerThreads() : base()
            {
                Location = new Point(100, 10);
                this.Minimum = 1;
                this.Maximum = 100;
            }
        }

        MyZedGraph zg1;
        public System.Windows.Forms.Timer timer1;
        Pool myThreadPool;
        NumericUpDown spinnerThreads;
        Button btnAddWorker;
        int x = 0;

        public void setPoolSize(object sender, EventArgs e)
        {
            myThreadPool.setSize((int)spinnerThreads.Value);
        }

        public ProgressDialog2(Pool myThreadPool)
        {
            this.myThreadPool = myThreadPool;
            spinnerThreads = new SpinnerThreads();
            spinnerThreads.Value = myThreadPool.intendedSize;
            spinnerThreads.ValueChanged += new EventHandler(setPoolSize);
            zg1 = new MyZedGraph();
            ClientSize = new Size(640, 800);
            Controls.Add(zg1);
            timer1 = new System.Windows.Forms.Timer();
            timer1.Interval = 1000;
            timer1.Start();
            timer1.Tick += timer1_Tick;
            Text = "ThreadPool Info";
            btnAddWorker = new Button();
            btnAddWorker.Text = "Add Worker";
            btnAddWorker.Click += new EventHandler(addWorker);
            //Controls.Add(btnAddWorker);
            Controls.Add(spinnerThreads);
        }

        void addWorker(object sender, EventArgs e)
        {
            myThreadPool.newWorker();
        }

        public void timer1_Tick(object sender, EventArgs e)
        {
            zg1.foo();
            x++;
            zg1.queue.Add(x, myThreadPool._tasks.Count);
            zg1.list2.Add(x, myThreadPool.busyWorkers.Count);
            zg1.completedCount.Add(x, myThreadPool.completedCount);
            zg1.myRefresh();
        }
    }

    public ParItStreamCLI() { }

    public void display()
    {
        Application.Run(new ProgressDialog2(myThreadPool));
    }

    private int run(string[] args)
    {
        Options options = new Options(args);
        options.parse();
        myThreadPool = new Pool(options.getThreads());
        int status = 0;

        if (options.getProgressionDialogSwitch())
        {
            pd2ThreadStart = new ThreadStart(display);
            pd2Thread = new Thread(pd2ThreadStart);
            pd2Thread.Start();
        }

        if (options.help())
        {
            help();
        }
        else if (options.getCreate())
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            ArchiveFactory factory;

            if (options.getDngs())
                factory = new DNGSArchiveFactory(null, myThreadPool);
            else if (options.getGzip())
                factory = new GZipArchiveFactory(null);
            else
                factory = new ArchiveFactory(null, myThreadPool);

            factory.createNew(Console.OpenStandardOutput(), options.files);
            sw.Stop();
            Console.Error.WriteLine("Archive created in: {0}", sw.Elapsed);
        }
        else if (options.getList())
        {
            ArchiveFactory factory = new ArchiveFactory();
            Archive archive = factory.load(Console.OpenStandardInput());
            FileHeaderIterator it = archive.getFileHeaderIterator();
            FileHeader current;

            do
            {
                current = it.next();
                Console.WriteLine(current);
            }
            while (current != null);
        }
        else if (options.getTest())
        {
            ArchiveFactory factory = new ArchiveFactory();
            Archive archive = factory.load(Console.OpenStandardInput());
            FileHandleIterator it = archive.getFileHandleIterator();
            FileHandle current;

            while ((current = it.next()) != null)
            {
                if (current.test2() == false)
                {
                    status = 1;
                    break;
                }
            }
        }
        else if (options.getExtract())
        {
            ArchiveFactory factory = new ArchiveFactory();
            Archive archive = factory.load(Console.OpenStandardInput());
            archive.extract(Directory.GetCurrentDirectory());
        }

        myThreadPool.quit();
        return status;
    }

    private void help()
    {
        Console.WriteLine("help");
    }

    public static int Main(string[] args)
    {
        ParItStreamCLI instance = new ParItStreamCLI();
        return instance.run(args);
    }
}





